#include "tcp_socket.h"

#include "global_variant.h"
// #include <cmath>
#include <QString>
#include <QSqlQuery>
#include <QSqlError>

// TcpSocket::TcpSocket(QTcpSocket *socket, qintptr socketDescriptor, QObject *parent)
// {
//     this->m_socket = socket;
//     m_ip = m_socket->peerAddress().toString();
//     m_ip = m_ip.replace("::ffff:", "");
//     m_port = m_socket->peerPort();

//     //记录套接字描述符
//     m_socketDescriptor = socketDescriptor;
// }

TcpSocket::TcpSocket(qintptr socketDescriptor, QObject *parent)
{
    qRegisterMetaType<QAbstractSocket::SocketError>("");
    qRegisterMetaType<QHash<QString, QList<int>>>("QHash<QString, QList<int>>");
    qRegisterMetaType<QHash<QString,int>>("QHash<QString,int>");


    Q_UNUSED(parent);
    //记录套接字描述符
    m_socketDescriptor = socketDescriptor;

    //数据库连接名
    m_detailInformationDatabaseConnectedName += QString::number(socketDescriptor, 10);

    m_studentGradeDatabaseConnectedName += QString::number(socketDescriptor, 10);

    m_totalInformationDatabaseConnectedName += QString::number(socketDescriptor, 10);
}

void TcpSocket::initializeTcpSocketFunction()
{

    this->m_socket = new QTcpSocket(this);
    m_socket->setSocketDescriptor(m_socketDescriptor);


    m_ip = m_socket->peerAddress().toString();
    m_ip = m_ip.replace("::ffff:", "");
    m_port = m_socket->peerPort();

    qDebug()<<"initializeTcpSocketFunction():"<<QThread::currentThreadId() << QThread::currentThread();

    //套接字发生错误
    connect(m_socket, &QAbstractSocket::errorOccurred, this, [=](QAbstractSocket::SocketError){
        QTcpSocket* sock = (QTcpSocket*)sender();
        qDebug() << "Socket error:" << sock->errorString();
    });

    //套接字断开连接
    connect(m_socket, &QTcpSocket::disconnected,
            this, &TcpSocket::disconnected);

    //接受数据
    connect(m_socket, &QTcpSocket::readyRead,
            this, &TcpSocket::readData);

    //心跳计时
    if(m_isCreateheartBeatTimingStatisticsTimer == false){
        qDebug()<<"开始心跳计时统计";

        m_isCreateheartBeatTimingStatisticsTimer = true;

        m_heartBeatTimingStatisticsTimer = new QTimer;

        m_heartBeatTimingStatisticsTimer->setTimerType(Qt::PreciseTimer);
    }

    connect(m_heartBeatTimingStatisticsTimer, &QTimer::timeout,
            this, [&](){

            if(m_heartBeatTimingStatisticsTimerCount - 1 >= 0){
                QMutexLocker locker(&m_heartBeatTimingStatisticsTimerCountMutex);
                m_heartBeatTimingStatisticsTimerCount--;
            }else{
                disconnected();
            }
                // m_heartBeatTimingStatisticsTimer->stop();
                // m_heartBeatTimingStatisticsTimer->setInterval(0);
    });

    m_heartBeatTimingStatisticsTimer->start(m_heartBeatTimingRefreshTime);



    // m_routeEquipmentExamTimingStatisticsTimer = new QTimer;

    // m_routeEquipmentExamTimingStatisticsTimer->setTimerType(Qt::PreciseTimer);


    // m_isCreateRouteEquipmentExamTimingStatisticsTimer = true;
    // g_insertRouteEquipmentExamTimeoutRecord = false;


}


TcpSocket::~TcpSocket()
{
    //释放定时发送的计时器
    if(m_isCreateheartBeatTimingStatisticsTimer){
        m_heartBeatTimingStatisticsTimer->disconnect();
        m_heartBeatTimingStatisticsTimer->deleteLater();
    }

    //释放该连接时，需要先获取该连接的连接名，然后先关闭当前数据库，并将当前数据库使用默认构造函数覆盖，最后再移除当前连接。
    //如果建立了数据库连接，就是释放连接
    if(m_createDetailInformationDatabaseConnection){
        m_detailInformationDB.close();
        m_detailInformationDB = QSqlDatabase();
        QSqlDatabase::removeDatabase(m_detailInformationDatabaseConnectedName);//断开与数据库的连接
    }




}

//接受株所发送的硬件信号
void TcpSocket::readData()
{
    if(m_socket->bytesAvailable() == 0){
        //qDebug()<<"没有残留的信息";
        return;
    }

    //接受到的消息小于12个字节并且消息体为0
    if(m_receivedBytes < m_frameHeadLength && m_infoBlock.length() == 0){
        //完整的读完一个消息头（可读套接字大于等于12个字节，并且现存的帧头等于0）
        if(m_socket->bytesAvailable() >= m_frameHeadLength && m_frameHead.size() == 0){
            m_frameHead = m_socket->read(m_frameHeadLength);
            qDebug()<<"m_frameHead:"<<byteArrayToHexStr(m_frameHead);//.toHex().toUpper();
        }else{
            //qDebug()<<"接收头返回";
            return;
        }
    }

    //解析帧头的信息
    if(m_frameHead.size() != 0 && m_frameHead.size() == 12 && m_length.size() == 0){
        qDebug()<<"解析帧头";

        m_length = m_frameHead.mid(2,2);
        m_command = m_frameHead.mid(4,4);
        m_serialNumber = m_frameHead.mid(8,4);

        qDebug()<<"帧头中长度:"<<byteArrayToHexStr(m_length);
        qDebug()<<"帧头中命令:"<<byteArrayToHexStr(m_command);
        qDebug()<<"帧头中序列号:"<<byteArrayToHexStr(m_serialNumber);

        bool ok;
        m_totalBytes = m_length.toHex().toInt(&ok,16);

        m_receivedBytes += 12;
    }

    //帧头不对，丢弃该包数据
    if(m_totalBytes == 0 || m_totalBytes >= 15000 || m_frameHead.mid(0,2).toHex().toUpper() != QString("FFD8")){
        ////qDebug()<<"错误b_frameHead:"<<s_frameHead.toHex().toUpper();
        m_infoBlock.resize(0);
        m_receivedBytes = 0;
        m_totalBytes = 0;
        m_frameHead.resize(0);
        m_length.resize(0);

        QByteArray tmpAbortData = m_frameContent + m_socket->readAll();
        qDebug()<<"目前丢弃的数据："<<tmpAbortData;

        return;
    }

    //持续接受数据,直到完整的接受完数据
    if(m_receivedBytes < m_totalBytes && m_socket->bytesAvailable() > 0){
        //QByteArray inBlock = tcpSocket->readAll();
        //收到的数据包含下一帧数据
        if(m_socket->bytesAvailable() >= m_frameHeadLength){
            m_tmpBlock = m_socket->read(m_totalBytes - m_receivedBytes);
        }else{//收到的数据仅是本帧数据
            m_tmpBlock = m_socket->readAll();
        }

        m_infoBlock.append(m_tmpBlock);

        m_receivedBytes += m_tmpBlock.size();
        //qDebug()<<"inBlock:"<<byteArrayToHexStr(inBlock);
        //qDebug()<<"持续接收receivedBytes:"<<receivedBytes;
        m_tmpBlock.resize(0);
    }

    //处理数据
    if(m_receivedBytes == m_totalBytes){
        qDebug()<<"m_infoBlock:"<<m_infoBlock;
        qDebug()<<"m_totalBytes:"<<m_totalBytes;

        QByteArray wholeInfoBlock = m_frameHead + m_infoBlock;
        qDebug()<<"收到的全部数据:"<<wholeInfoBlock;

        //取出消息体，抛去（消息尾）
        //m_infoBlock；存储除去消息头的全部内容
        m_frameContent = m_infoBlock.mid(0, m_totalBytes - 15);

        //取帧尾
        m_frameTail = wholeInfoBlock.mid(12 + m_frameContent.size(), 2);
        qDebug()<<"m_frameTail："<<m_frameTail.toHex().toUpper();

        //帧尾不对，丢弃数据
        if(m_frameTail.toHex().toUpper() != QString("FFD9")){
            m_infoBlock.resize(0);
            m_receivedBytes = 0;
            m_totalBytes = 0;
            m_frameHead.resize(0);
            m_length.resize(0);

            QByteArray tmpAbortData = wholeInfoBlock + m_socket->readAll();
            qDebug()<<"帧尾不对，目前丢弃的全部数据："<<tmpAbortData;

            return;
        }

        //取出异或校验的值
        QByteArray checkTemplate = m_infoBlock.right(1);

        //得到BCC校验的对象(头+体【抛去固定头12位和异或校验位1位】)
        //异或校验不对，丢弃数据
        QByteArray checkContent = m_frameHead +  m_infoBlock.mid(0, m_totalBytes - 13);
        qDebug()<<"checkContent:"<<checkContent;
        if(getOrCode(checkContent) == checkTemplate.toHex().toUpper()){
            qDebug()<<getOrCode(checkContent);

            qDebug()<<"BCC校验正确";
        }else{
            qDebug()<<"BCC校验失败";
            //对收到命令的第一个字节 + 80；例如收到10，回复90
            //QString msg = m_command.mid(0,1).toHex();
            //int num = msg.toInt(NULL,16);
            //m_commandNumber.OneByte =QByteArray::fromHex(QByteArray::number(num + 128,16)).at(0);

            m_commandNumber.OneByte = m_command.at(0);
            m_commandNumber.TwoByte = m_command.at(1);
            m_commandNumber.ThreeByte = m_command.at(2);
            m_commandNumber.FourByte = m_command.at(3);

            QByteArray data;
            data += ChecksumError;

            QByteArray buffer = dealSendData(m_commandNumber, data);

            m_socket->write(buffer);

            //发送处理的数据
            emit receiveData(m_ip, m_port, "BCC校验错误");
            //重置数据
            m_infoBlock.resize(0);
            m_receivedBytes = 0;
            m_totalBytes = 0;
            m_frameHead.resize(0);
            m_length.resize(0);

            return;
        }

        //发送处理的数据
        // emit receiveData(m_ip, m_port, byteArrayToAsciiStr(m_frameContent));


       // emit receiveData(m_ip, m_port, QString::fromUtf8(m_frameContent));
        qDebug() << "Test currentThread 1：" <<QThread::currentThreadId() << QThread::currentThread();

        //处理接受的数据
        qDebug()<<"处理接受的socket数据";
        dealRecieveData(m_command, m_frameContent);

        //重置数据
        m_infoBlock.resize(0);
        m_receivedBytes = 0;
        m_totalBytes = 0;
        m_frameHead.resize(0);
        m_length.resize(0);
    }

    //递归处理数据
    if(m_socket->bytesAvailable() > 0){
        readData();
    }
}

//处理接受数据【分】；（创建数据库连接）
void TcpSocket::dealRecieveData(QByteArray command, QByteArray frameContent)
{
    qDebug() << "接受数据的线程：" <<QThread::currentThreadId() << QThread::currentThread();

    //心跳断联
    if(m_isCreateheartBeatTimingStatisticsTimer){
        QMutexLocker locker(&m_heartBeatTimingStatisticsTimerCountMutex);
        m_heartBeatTimingStatisticsTimerCount = 3;
    }

    // QString data = QString::fromUtf8(frameContent);
    // qDebug()<<"data:"<<data;
    QString data;

    //对比指令并处理
    QString constrastCommand = command.toHex().toUpper();
    qDebug()<<"constrastCommand :"<<constrastCommand;

    if(constrastCommand == QString("00000000")){//上电登录请求

        //建立详细信息数据库连接
        if(m_createDetailInformationDatabaseConnection == false){
            if(CreateDatabaseConnection(m_detailInformationDB,
                                        m_detailInformationDatabaseIp,
                                        m_detailInformationDatabasePort,
                                        m_detailInformationDatabaseName,
                                        m_detailInformationDatabaseAccount,
                                        m_detailInformationDatabasePassword,
                                        m_detailInformationDatabaseConnectedName)){
                m_createDetailInformationDatabaseConnection = true;
            }
        }

        //建立学生成绩数据库连接
        if(m_createStudentGradeDatabaseConnection == false){
            if(CreateDatabaseConnection(m_studentGradeDB,
                                         m_studentGradeDatabaseIp,
                                         m_studentGradeDatabasePort,
                                         m_studentGradeDatabaseName,
                                         m_studentGradeDatabaseAccount,
                                         m_studentGradeDatabasePassword,
                                         m_studentGradeDatabaseConnectedName)){
                m_createDetailInformationDatabaseConnection = true;
            }
        }

        //建立总数据库连接
        if(m_createTotalInformationDatabaseConnection == false){
            if(CreateDatabaseConnection(m_totalInformationDB,
                                         m_totalInformationDatabaseIp,
                                         m_totalInformationDatabasePort,
                                         m_totalInformationDatabaseName,
                                         m_totalInformationDatabaseAccount,
                                         m_totalInformationDatabasePassword,
                                         m_totalInformationDatabaseConnectedName)){
                m_createTotalInformationDatabaseConnection = true;
            }
        }


        qDebug()<<"data:"<<frameContent.toHex().toUpper();

        QString equipmentType = frameContent.toHex().toUpper();

        //关联ip、端口和设备类型
        if(equipmentType == "03"){//环车检查设备
            g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment] = QPair(getIP(), getPort());
            g_Hash2Client[QPair(getIP(), getPort())] = ClientHashEnum::ExamineExamUnityEquipment;


            qDebug()<<"equipmentType == 00";

            emit conveyEquipmentStatusType(EquipmentStatusType::ExamineExamUnityEquipmentOnline);
        }else if(equipmentType == "04"){//驾驶设备
            g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment] = QPair(getIP(), getPort());
            g_Hash2Client[QPair(getIP(), getPort())] = ClientHashEnum::RouteExamUnityEquipment;

            emit conveyEquipmentStatusType(EquipmentStatusType::RouteExamUnityEquipmentOnline);
        }else if(equipmentType == "05"){//捣鼓作业
            g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment] = QPair(getIP(), getPort());
            g_Hash2Client[QPair(getIP(), getPort())] = ClientHashEnum::TampingHomeworkEquipment;

            emit conveyEquipmentStatusType(EquipmentStatusType::TampingHomeworkEquipmentOnline);
        }else if(equipmentType == "06"){//下位机设备（株所）
            g_Client2Hash[ClientHashEnum::LowerComputerCommucationEquipment] = QPair(getIP(), getPort());
            g_Hash2Client[QPair(getIP(), getPort())] = ClientHashEnum::LowerComputerCommucationEquipment;

            emit conveyEquipmentStatusType(EquipmentStatusType::LowerComputerEquipmentOnline);
        }


        //上电登录回复
        // CommondNumber commond;
        // commond.OneByte = 0x80;
        // commond.TwoByte = 0x00;
        // commond.ThreeByte = 0x00;
        // commond.FourByte = 0x00;
        // QByteArray sendByteArray;

        // m_socket->write(dealSendData3(commond, sendByteArray));

        m_socket->write(dealSendData2(QString("")));

    }

    if(constrastCommand == QString("31000000")){//心跳回复

        // CommondNumber tmpCommond;
        // QByteArray tmpContentByteArray;

        // tmpCommond.OneByte = 0xB1;
        // tmpCommond.TwoByte = 0x00;
        // tmpCommond.ThreeByte = 0x00;
        // tmpCommond.FourByte = 0x00;

        // sendSocketData(m_ip,
        //                m_port,
        //                tmpCommond,
        //                tmpContentByteArray);

        m_socket->write(dealSendData2(QString("")));
    }

    else if(constrastCommand == QString("0A000000")){//成功登录
        if(m_ip == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first
            && m_port == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second){
            emit conveyEquipmentStatusType(EquipmentStatusType::ExamineExamUnityEquipmentLogIn);

            if(g_isExecuteEquipmentExam == true){
                qDebug()<<"成功登录运行前检查";

                /*
                 * 1,删除旧表；
                 * 2，创建考试表；
                 * 3，考试表本地初始化；
                 * 4，考试计时；
                */

                QList<QString> sqlSentenceList;

                g_examineExamCreatetimestamp = QDateTime::currentSecsSinceEpoch();

                g_examineExamTableName =  QString("%1_%2_tmp_%3")
                                              .arg(g_examineExamUnityAccount)
                                              .arg("examine_exam")
                                              .arg(g_examineExamCreatetimestamp);

                //1，删除残余的旧表
                //查询scheme表【全部数据库的表】
                QString sql= "Select CONCAT( 'drop table if exists ', table_name, ';' )"
                              " FROM information_schema.tables"
                              " Where table_name LIKE '%examine_exam_tmp%';";
                QSqlQuery query(m_detailInformationDB);
                if(!query.exec(sql)){
                    qDebug()<<query.lastError().databaseText();
                }else{
                    while(query.next()){
                        sqlSentenceList.append(query.value(0).toString());
                        qDebug()<<"删除线路驾驶的旧表:"<<query.value(0).toString();
                    }
                }

                //2，创建考试表
                //sqlSentenceList.append(QString("drop table if exists examine_exam1"));
                sql = QString("CREATE TABLE %1 SELECT * FROM examine_exam_template").arg(g_examineExamTableName);
                qDebug()<<"创建考试表:"<<sql;
                sqlSentenceList.append(sql);
                execTransactionSqlSentence(m_detailInformationDB, sqlSentenceList);

                //3，初始化考试表到本地
                initializeExamineExamTable();

                //4，考试计时
                if(m_isCreateExecuteEquipmentExamTimingStatisticsTimer == false){
                    qDebug()<<"创建考试计时器";
                    m_executeEquipmentExamTimingStatisticsTimer = new QTimer;

                    m_executeEquipmentExamTimingStatisticsTimer->setTimerType(Qt::PreciseTimer);

                    connect(m_executeEquipmentExamTimingStatisticsTimer, &QTimer::timeout,
                            this, [&](){
                                qDebug()<<"考试超时";
                                g_isExecuteEquipmentExamTimeout = true;

                                m_executeEquipmentExamTimingStatisticsTimer->stop();
                                m_executeEquipmentExamTimingStatisticsTimer->setInterval(0);

                            });

                    m_isCreateExecuteEquipmentExamTimingStatisticsTimer = true;

                    g_insertExecuteEquipmentExamTimeoutRecord = false;
                }

                m_executeEquipmentExamTimingStatisticsTimer->start(m_examTimeoutMsec);

            }
        }else if(m_ip == g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].first
            && m_port == g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].second){
            qDebug()<<"线路驾驶的待写成功登录：待写";
        }else if(m_ip == g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].first
                && m_port == g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].second){
            qDebug()<<"捣固作业的待写成功登录：待写";
        }
    }

    else if(constrastCommand == QString("32000000")){//考试结束

        if(m_ip == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first && m_port == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second){
            if(g_isExecuteEquipmentExam == true){
                qDebug()<<"收到的unity端语音内容："<<QString::fromUtf8(frameContent);

                g_voiceRecord1 = QString::fromUtf8(frameContent);
                //得到环车检查的主观成绩
                emit getExamStepSubjectivePoint(ExamType::ExamineExam);
            }else{
                CommondNumber commond;
                commond.OneByte = 0xB2;
                commond.TwoByte = 0x00;
                commond.ThreeByte = 0x00;
                commond.FourByte = 0x00;
                QByteArray sendByteArray;

                m_socket->write(dealSendData3(commond, sendByteArray));

                emit conveyEquipmentStatusType(EquipmentStatusType::ExamineExamUnityEquipmentLogOut);
            }
        }

    }

    else if(constrastCommand == QString("10000000")){//客户端收到退出登录
        //环车检查设备
        if(m_ip == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first && m_port == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second){
            //如果是考试模式，则计算考试成绩
            if(g_isExecuteEquipmentExam == true){
                m_executeEquipmentExamTimingStatisticsTimer->stop();
                m_executeEquipmentExamTimingStatisticsTimer->setInterval(0);

                if(g_insertExecuteEquipmentExamTimeoutRecord == false
                    && g_isExecuteEquipmentExamTimeout == true){
                    insertExamTableTimeoutResult(g_examineExamTableName);

                    g_insertExecuteEquipmentExamTimeoutRecord = true;
                }

                //发送总成绩
                g_voiceRecord1 = QString::fromUtf8(frameContent);
                qDebug()<<"收到的unity端语音内容："<<g_voiceRecord1;


                //计算开始成绩
                //calculateFinalExamineExamGrade();

                //统计考试情况
                statisticExamSituation(m1_examSubstepNumberRecord, m1_examSituationStatistic);

                //发送考试总成绩或考试情况
                CommondNumber tmpCommond;
                QByteArray tmpContentByteArray;
                tmpContentByteArray.resize(8);

                tmpCommond.OneByte = 0xB2;
                tmpCommond.TwoByte = 0x00;
                tmpCommond.ThreeByte = 0x00;
                tmpCommond.FourByte = 0x00;


                //double--->QByteArray
                // double num = 10.2;
                // QByteArray data;
                // data.resize(4);
                // memcpy(data.data(), &num, sizeof(num));
                // qDebug()<<data.toHex();

               // memcpy(tmpContentByteArray.data(), &m_executeEquipmentFinalGrade, sizeof(m_executeEquipmentFinalGrade));
                // qDebug()<< "发送的考试最终成绩："<<tmpContentByteArray;

                QByteArray shortDataResult;
                shortDataResult.resize(6);
                QByteArray tmpShortData;
                tmpShortData.resize(2);
                memcpy(tmpShortData.data(), &m1_examSituationStatistic["rightStep"], sizeof(tmpShortData));
                shortDataResult += tmpShortData;
                tmpShortData.clear();
                memcpy(tmpShortData.data(), &m1_examSituationStatistic["wrongStep"], sizeof(tmpShortData));
                shortDataResult += tmpShortData;
                tmpShortData.clear();
                memcpy(tmpShortData.data(), &m1_examSituationStatistic["unDoneStep"], sizeof(tmpShortData));
                shortDataResult += tmpShortData;


                sendSocketData(g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first,
                               g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second,
                               tmpCommond,
                               shortDataResult);

                //发送考试情况统计
                emit  sendExamSituation(ExamType::ExamineExam, m1_examSituationStatistic);

                g_isExecuteEquipmentExam = false;
            }
            emit conveyEquipmentStatusType(EquipmentStatusType::ExamineExamUnityEquipmentLogOut);

        }
    }

    else if(constrastCommand == QString("11000000")){//关闭设备
        if(m_ip == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first && m_port == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second){
            emit conveyEquipmentStatusType(EquipmentStatusType::ExamineExamUnityEquipmentOffline);
        }else if(m_ip == g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].first && m_port == g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].second){
            emit conveyEquipmentStatusType(EquipmentStatusType::RouteExamUnityEquipmentOffline);
        }else if(m_ip == g_Client2Hash[ClientHashEnum::LowerComputerCommucationEquipment].first && m_port == g_Client2Hash[ClientHashEnum::LowerComputerCommucationEquipment].second){
            emit conveyEquipmentStatusType(EquipmentStatusType::LowerComputerEquipmentOffline);
        }else if(m_ip == g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].first && m_port == g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].second){
            emit conveyEquipmentStatusType(EquipmentStatusType::TampingHomeworkEquipmentOffline);
        }
    }

    else if(constrastCommand.mid(0,2) == QString("1B")){//运行前检查
        qDebug()<<"进入运行前检查的流程";

        //信息回复
        //对收到命令的第一个字节 + 80；例如收到10，回复90
        QString msg = m_command.mid(0,1).toHex();
        int num = msg.toInt(NULL,16);

        CommondNumber tmpCommond;
        QByteArray tmpContentByteArray;
        tmpCommond.OneByte = QByteArray::fromHex(QByteArray::number(num + 128,16)).at(0);
        tmpCommond.TwoByte = m_command.at(1);
        tmpCommond.ThreeByte = m_command.at(2);
        tmpCommond.FourByte = m_command.at(3);

        sendSocketData(m_ip,
                       m_port,
                       tmpCommond,
                       tmpContentByteArray);


        data = frameContent.toHex().toUpper();

        if(data == "00"){//正确
            qDebug()<<constrastCommand<<":正确";
            dealExamineExamGrade(constrastCommand, 1);
        }else if(data == "01"){//错误
            qDebug()<<constrastCommand<<":错误";
            dealExamineExamGrade(constrastCommand, 2);
        }

        //实时计算考试情况
        dealExamineExamDetailSituation();
    }
}

//发送套接字数据
void TcpSocket::sendSocketData(const QString &ip, int port, QByteArray data)
{
    qDebug() << "Test currentThread 4：" <<QThread::currentThreadId() << QThread::currentThread();

    if(ip == m_ip && port == m_port){
        qDebug()<<"TcpClient::sendData1";
        if(m_command.size() == 0){
            m_commandNumber.OneByte = 0x01;
            m_commandNumber.TwoByte = 0x00;
            m_commandNumber.ThreeByte = 0x00;
            m_commandNumber.FourByte = 0x00;
        }

        QByteArray sendMessage;
        sendMessage.append((char*)&m_commandNumber, sizeof(m_commandNumber));//结构体转QByteArry
        qDebug()<<"TcpClient::sendSocketData m_commond:"<<sendMessage;

        QByteArray buffer = dealSendData3(m_commandNumber, data);

        m_socket->write(buffer);
        emit conveySendData2MainInterface(m_ip, m_port, data);
    }
}

void TcpSocket::sendSocketData(const QString &ip, int port, CommondNumber command, QByteArray data)
{
    if(ip == m_ip && port == m_port){
        qDebug()<<"TcpClient::sendData2";

        // QByteArray sendMessage;
        // sendMessage.append((char*)&command, sizeof(command));//结构体转QByteArry
        // qDebug()<<"TcpClient::sendSocketData m_commond:"<<sendMessage;

        QByteArray buffer = dealSendData3(command, data);

        m_socket->write(buffer);
        emit conveySendData2MainInterface(m_ip, m_port, data);
    }
}


//处理用户登录：1，登入；2，退出登录
void TcpSocket::dealUserLogStatus(int equipmentStatusType, int examType, int examPatternType, QString account, QHash<QString, QList<int> > faultType)
{
    ////
    ///     qDebug()<<"void TcpClient::dealUserLogStatus";

    CommondNumber commond;
    QByteArray contentByteArray = account.toUtf8();
    uchar tmpChar = 0x00;
    // //账号信息
    commond.OneByte = 0x83;
    commond.TwoByte = 0x00;
    commond.ThreeByte = 0x00;
    commond.FourByte = 0x00;

    if(examPatternType == ExamPatternType::ExamType){
        if(examType == ExamType::ExamineExam){
            g_isExecuteEquipmentExam = true;

        }else if(examType == ExamType::RouteExam){
            g_isRouteEquipmentExam = true;
            // g_routeEquipmentExamType = examType;

        }else if(examType == ExamType::TampingHomeworkExam){
            g_isTampingHomeworkEquipmentExam = true;
        }
    }

    if(equipmentStatusType == ClientHashEnum::ExamineExamUnityEquipment){
        if(examType == ExamType::ExamineExam){
            /*
             * 1，发送账号信息；
             * 2，发送模式信息；
             * 3，发送考试类型
             * 4，发送故障类型
            */



            //1，发送账号信息
            sendSocketData(g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first,
                           g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second,
                           commond,
                           contentByteArray);

            //2，模式信息（训练、考试）
            commond.OneByte = 0x85;
            commond.TwoByte = 0x00;
            commond.ThreeByte = 0x00;
            commond.FourByte = 0x00;
            contentByteArray.clear();
            if(examPatternType == ExamPatternType::TrainingType){
                contentByteArray += tmpChar;
            }else if(examPatternType == ExamPatternType::ExamType){
                contentByteArray += 0x01;
            }

            sendSocketData(g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first,
                           g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second,
                           commond,
                           contentByteArray);

            //3，考试类型（任务场景：运行前检查00，线路驾驶02，捣固作业03）
            commond.OneByte = 0x84;
            commond.TwoByte = 0x00;
            commond.ThreeByte = 0x00;
            commond.FourByte = 0x00;

            contentByteArray.clear();

            contentByteArray.append(tmpChar);

            sendSocketData(g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first,
                           g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second,
                           commond,
                           contentByteArray);

            //4，发送故障类型（仅考试模式设置故障）
            if(examPatternType == ExamPatternType::ExamType){
                //机械故障类型
                commond.OneByte = 0x86;
                commond.TwoByte = 0x00;
                commond.ThreeByte = 0x00;
                commond.FourByte = 0x00;

                contentByteArray.clear();

                //int转一个字节的Byte
                contentByteArray.append(faultType["机械故障"].at(0)&(0x000000ff));

                sendSocketData(g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first,
                               g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second,
                               commond,
                               contentByteArray);
            }


        }else if(examType == ExamType::ExitType){
            commond.OneByte = 0x90;
            commond.TwoByte = 0x00;
            commond.ThreeByte = 0x00;
            commond.FourByte = 0x00;
            contentByteArray.clear();

            // QByteArray tmpContentByteArray;
            // tmpContentByteArray.resize(8);
            // memcpy(tmpContentByteArray.data(), &m_executeEquipmentFinalGrade, sizeof(m_executeEquipmentFinalGrade));

            sendSocketData(g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first,
                           g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second,
                           commond,
                           contentByteArray);
        }
    }else if(equipmentStatusType == ClientHashEnum::RouteExamUnityEquipment){
        if(examType == ExamType::RouteExam){
            /*
             * 1，发送账号信息；
             * 2，发送模式信息；
             * 3，发送考试类型
             * 4，发送故障类型
            */

            //1，发送账号信息
            sendSocketData(g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].first,
                           g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].second,
                           commond,
                           contentByteArray);

            //2，模式信息（训练、考试）
            commond.OneByte = 0x85;
            commond.TwoByte = 0x00;
            commond.ThreeByte = 0x00;
            commond.FourByte = 0x00;
            contentByteArray.clear();
            if(examPatternType == ExamPatternType::TrainingType){
                contentByteArray += tmpChar;
            }else if(examPatternType == ExamPatternType::ExamType){
                contentByteArray += 0x01;
            }

            sendSocketData(g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].first,
                           g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].second,
                           commond,
                           contentByteArray);

            //3，考试类型（任务场景：运行前检查00，线路驾驶02，捣固作业03）
            commond.OneByte = 0x84;
            commond.TwoByte = 0x00;
            commond.ThreeByte = 0x00;
            commond.FourByte = 0x00;

            contentByteArray.clear();

            contentByteArray.append(0x02);

            sendSocketData(g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].first,
                           g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].second,
                           commond,
                           contentByteArray);

            //4,故障



        }else if(examType == ExamType::ExitType){
            commond.OneByte = 0x90;
            commond.TwoByte = 0x00;
            commond.ThreeByte = 0x00;
            commond.FourByte = 0x00;
            contentByteArray.clear();

            // QByteArray tmpContentByteArray;
            // tmpContentByteArray.resize(8);
            // memcpy(tmpContentByteArray.data(), &m_executeEquipmentFinalGrade, sizeof(m_executeEquipmentFinalGrade));

            sendSocketData(g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].first,
                           g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].second,
                           commond,
                           contentByteArray);
        }
    }else if(equipmentStatusType == ClientHashEnum::TampingHomeworkEquipment){
        if(examType == ExamType::TampingHomeworkExam){
            /*
             * 1，发送账号信息；
             * 2，发送模式信息；
             * 3，发送考试类型
             * 4，发送故障类型
            */

            //1，发送账号信息
            sendSocketData(g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].first,
                           g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].second,
                           commond,
                           contentByteArray);

            //2，模式信息（训练、考试）
            commond.OneByte = 0x85;
            commond.TwoByte = 0x00;
            commond.ThreeByte = 0x00;
            commond.FourByte = 0x00;
            contentByteArray.clear();
            if(examPatternType == ExamPatternType::TrainingType){
                contentByteArray += tmpChar;
            }else if(examPatternType == ExamPatternType::ExamType){
                contentByteArray += 0x01;
            }

            sendSocketData(g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].first,
                           g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].second,
                           commond,
                           contentByteArray);

            //3，考试类型（任务场景：运行前检查00，线路驾驶02，捣固作业03）
            commond.OneByte = 0x84;
            commond.TwoByte = 0x00;
            commond.ThreeByte = 0x00;
            commond.FourByte = 0x00;

            contentByteArray.clear();

            contentByteArray.append(0x03);

            sendSocketData(g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].first,
                           g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].second,
                           commond,
                           contentByteArray);


        }else if(examType == ExamType::ExitType){
            commond.OneByte = 0x90;
            commond.TwoByte = 0x00;
            commond.ThreeByte = 0x00;
            commond.FourByte = 0x00;
            contentByteArray.clear();

            // QByteArray tmpContentByteArray;
            // tmpContentByteArray.resize(8);
            // memcpy(tmpContentByteArray.data(), &m_executeEquipmentFinalGrade, sizeof(m_executeEquipmentFinalGrade));

            sendSocketData(g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].first,
                           g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].second,
                           commond,
                           contentByteArray);
        }
    }
}

//创建数据库连接
bool TcpSocket::CreateDatabaseConnection(QSqlDatabase& mysqlDB, QString ip, int port, QString dataBaseName, QString databaseAccount, QString dataBasePassword, QString databaseConnectName)
{
    qDebug() << "详细清空数据库创建的线程：" <<QThread::currentThreadId() << QThread::currentThread();

    //设置数据库驱动
    mysqlDB = QSqlDatabase::addDatabase("QMYSQL", databaseConnectName);
    mysqlDB.setHostName(ip);
    mysqlDB.setPort(port);
    mysqlDB.setDatabaseName(dataBaseName);
    mysqlDB.setUserName(databaseAccount);
    mysqlDB.setPassword(dataBasePassword);

    //根据系统环境设计数据库路径
    // Q_OS_LINUX：Q_OS_WIN： Q_OS_MAC   Q_OS_WIN32

    //如果远程mysql数据库没有打开
    if(!mysqlDB.open()){
        qDebug()<<QString("数据库连接未成功:%1").arg(databaseConnectName);
        return false;
    }else{

#ifdef Q_OS_WIN
        mysqlDB.exec("SET NAMES 'GBK'");
#endif
#ifdef Q_OS_MAC

#endif
    }
    return true;
}

//事务执行sql事务
bool TcpSocket::execTransactionSqlSentence(QSqlDatabase mysqlDB, QList<QString> sqlSentenceList)
{
    QSqlQuery query(mysqlDB);
    QList<bool> execResultList;
    bool execResult = false;

    if(mysqlDB.transaction()){//创建考试表
        foreach (QString sql, sqlSentenceList){
            execResult = query.exec(sql);
            execResultList.append(execResult);
        }

        foreach (bool result, execResultList){
            if(result == false){
                if(!mysqlDB.rollback())
                    qDebug() << "db.lastError()"<<mysqlDB.lastError().databaseText(); //数据回滚
                return false;
            }
        }

        if(mysqlDB.commit()){
            qDebug()<<"提交成功";
            return true;
        }else{
            return false;
        }
    }
    return false;
}

//运行前检查
void TcpSocket::initializeExamineExamTable()
{

    QSqlQuery query(m_detailInformationDB);
    QString sql = QString("SELECT id,"
                          "exam_substep_number,"
                          "step_total_point,"
                          "step_deduct_point,"
                          "error_reason"
                          " FROM %1").arg(g_examineExamTableName);

    m1_examSubstepNumberHash.clear();

    if(query.exec(sql)){
        while(query.next()){
            m1_examExecuteStepActualCount[query.value(0).toString()] = query.value(1).toString().count(',');//考试实际执行步骤
            m1_examStepTotalPoint[query.value(0).toString()] = query.value(2).toDouble();//考试单步总分
            m1_examStepDeductPoint[query.value(0).toString()] = query.value(3).toDouble();//考试单步扣分
            m1_examStepObjectPoint[query.value(0).toString()] = 0.0;//单步客观得分
            m1_examStepSubobjectPoint[query.value(0).toString()] = 0.0;//单步主观得分
            m1_examStepFinalPoint[query.value(0).toString()] = 0.0;//单步最终总分
            m1_errorReason[query.value(0).toString()] = query.value(4).toString();//错误原因

            //子步骤操作记录
            QStringList examSubstepNumberList = query.value(1).toString().split(",");
            examSubstepNumberList.removeLast();//删除最后一个空值


            foreach (QString step, examSubstepNumberList) {

                if(g_isExecuteEquipmentExam == false){
                    m1_examSubstepNumberRecord[step] = 0;
                    g1_examSubstepNumberRecord[step] = 0;

                    g1_executeIndex = 0;
                }else{//使用之前的数据
                    m1_examSubstepNumberRecord[step] =  g1_examSubstepNumberRecord[step];
                    m1_executeIndex = g1_executeIndex;
                }
                m1_examSubstepNumberHash[query.value(0).toString()].append(step);
            }
        }
    }else{
        qDebug()<<query.lastError().databaseText();
    }

}

//插入超时记录
void TcpSocket::insertExamTableTimeoutResult(QString tableName)
{
    qDebug()<<"插入线路考试超时内容";
    QString sql = QString("INSERT INTO %1 (id, execute_step_id, exam_step_number, exam_step_describe, "
                          "exam_substep_number ,step_total_point, step_deduct_point, step_object_point,"
                          " step_subjective_point, step_final_point, step_result, error_reason) VALUES ("
                          "\'0F0000\', NULL, \'0F00\', \'考试超过规定35min\',"
                          "\'none\', 0.0, 0.00, 0.00,"
                          "0.0, 0.00, \'错误\',\'考试超时\')").arg(tableName);

    QSqlQuery query(QSqlDatabase::database(m_detailInformationDatabaseConnectedName));

    if(!query.exec(sql)){
        qDebug()<<query.lastError().databaseText();
    }else{
        if(tableName == g_examineExamTableName){
            g_insertExecuteEquipmentExamTimeoutRecord = true;
        }else if(tableName == g_routeExamTableName){
            g_insertRouteEquipmentExamTimeoutRecord = true;
        }

    }
}

//统计考试情况
void TcpSocket::statisticExamSituation(QHash<QString, int> examSubstepNumberRecord, QHash<QString, int>& examSituationStatistic)
{
    int rightStep = 0;
    int wrongStep = 0;
    int unDoneStep = 0;

    for(QHash<QString, int>::Iterator iter = examSubstepNumberRecord.begin();iter != examSubstepNumberRecord.end();iter++){
        if(iter.value() == 1){
            rightStep++;
        }else if(iter.value() == 2){
            wrongStep++;
        }else if(iter.value() == 0){
            unDoneStep++;
        }
    }

    examSituationStatistic["rightStep"] = rightStep;
    examSituationStatistic["wrongStep"] = wrongStep;
    examSituationStatistic["unDoneStep"] = unDoneStep;
}

//计算考试情况，并发送考试情况
void TcpSocket::calculateExamSituation(int examtype)
{
    if(examtype == ExamType::ExamineExam){
        if(g_isExecuteEquipmentExam){
            g_isExecuteEquipmentExam = false;

            if(m_isCreateExecuteEquipmentExamTimingStatisticsTimer){
                m_executeEquipmentExamTimingStatisticsTimer->stop();
                m_executeEquipmentExamTimingStatisticsTimer->setInterval(0);
            }

            if(g_insertExecuteEquipmentExamTimeoutRecord == false
                && g_isExecuteEquipmentExamTimeout == true){
                insertExamTableTimeoutResult(g_examineExamTableName);

                g_insertExecuteEquipmentExamTimeoutRecord = true;
            }


            //计算和显示最终考试成绩
            statisticExamSituation(m1_examSubstepNumberRecord, m1_examSituationStatistic);

            //发送考试总成绩
            CommondNumber tmpCommond;
            QByteArray tmpContentByteArray;
            tmpContentByteArray.resize(8);

            tmpCommond.OneByte = 0xB2;
            tmpCommond.TwoByte = 0x00;
            tmpCommond.ThreeByte = 0x00;
            tmpCommond.FourByte = 0x00;

            //double--->QByteArray
            // double num = 10.2;
            // QByteArray data;
            // data.resize(4);
            // memcpy(data.data(), &num, sizeof(num));
            // qDebug()<<data.toHex();

            // memcpy(tmpContentByteArray.data(), &m_executeEquipmentFinalGrade, sizeof(m_executeEquipmentFinalGrade));

            QByteArray shortDataResult;
            shortDataResult.resize(6);
            QByteArray tmpShortData;
            memcpy(tmpShortData.data(), &m1_examSituationStatistic["rightStep"], sizeof(m1_examSituationStatistic[""]));
            shortDataResult += tmpShortData;
            tmpShortData.clear();
            memcpy(tmpShortData.data(), &m1_examSituationStatistic["wrongStep"], sizeof(m1_examSituationStatistic[""]));
            shortDataResult += tmpShortData;
            tmpShortData.clear();
            memcpy(tmpShortData.data(), &m1_examSituationStatistic["unDoneStep"], sizeof(m1_examSituationStatistic[""]));
            shortDataResult += tmpShortData;

            sendSocketData(g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first,
                           g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second,
                           tmpCommond,
                           shortDataResult);

            //发送退出登录
            emit conveyEquipmentStatusType(EquipmentStatusType::ExamineExamUnityEquipmentLogOut);

            //发送考试情况
            emit  sendExamSituation(ExamType::ExamineExam, m1_examSituationStatistic);

        }else{
            qDebug()<<"二次进入计算运行前检查的考试情况";
        }
    }


}

////运行前检查
//单步计分:1，更新执行步骤；2，记录步骤对错
void TcpSocket::dealExamineExamGrade(QString stepId, int executeResult)
{
    QString id = "";
    QSqlQuery query(m_detailInformationDB);

    //查找详细步骤对应的考试步骤
    //SELECT id FROM route_exam  WHERE exam_substep_number LIKE '%0B00000C%'
    QString sql = QString("SELECT id, execute_step_id FROM %1 WHERE exam_substep_number LIKE '%%2%'").arg(g_examineExamTableName).arg(stepId);

    if(query.exec(sql)){
        while(query.next()){
            id = query.value(0).toString();
            if(query.value(1).isNull()){
                qDebug()<<"execute_step_id  is Null()";

                //更新执行步骤(如果之前没有更新过)
                //UPDATE route_exam SET execute_step_id = 3 WHERE id in (SELECT t.id FROM (SELECT id FROM route_exam  WHERE exam_substep_number LIKE '0B00000C' AND execute_step_id IS NULL)t)
                //sql = QString("UPDATE route_exam SET execute_step_id = \'%1\' WHERE id in (SELECT t.id FROM (SELECT id FROM route_exam  WHERE exam_substep_number LIKE '%%2%' AND execute_step_id IS NULL)t)").arg(++m_executeIndex).arg(stepId);
                sql = QString("UPDATE %3 SET execute_step_id = %1 WHERE id = \'%2\' AND execute_step_id IS NULL").arg(++m1_executeIndex).arg(id).arg(g_examineExamTableName);

                qDebug()<<"更新检查与实验的步骤："<<sql;

                if(!query.exec(sql)){
                    qDebug()<<query.lastError().databaseText();
                }
            }else{
                qDebug()<<"execute_step_id is not Null()";

                sql = QString("SELECT id, execute_step_id FROM %1 WHERE execute_step_id IS NOT NULL").arg(g_examineExamTableName);
                QHash<QString, int> executeStepIdHash;
                QVariantList idList;
                QVariantList executeStepIdList;
                if(query.exec(sql)){
                    while(query.next()){
                        executeStepIdHash[query.value(0).toString()] = query.value(1).toInt();
                    }

                    if(executeStepIdHash.size() > 1 && query.value(1).toInt() != m1_executeIndex){


                        //如果步骤序号大于当前的序号，则序号值减1，把当前序号值放到最后
                        for(QHash<QString, int>::Iterator iter = executeStepIdHash.begin(); iter != executeStepIdHash.end();iter++){
                            if(executeStepIdHash[iter.key()] > executeStepIdHash[id]){
                                idList<<iter.key();
                                executeStepIdList<< (iter.value() - 1);
                                qDebug()<<"iter.key():"<<iter.key();
                                qDebug()<<"(iter.value() - 1):"<<(iter.value() - 1);
                            }
                        }
                        idList<<id;
                        executeStepIdList<<m1_executeIndex;

                        sql = QString("UPDATE %1 SET execute_step_id = ? WHERE id = ?").arg(g_examineExamTableName);
                        query.prepare(sql);
                        query.addBindValue(executeStepIdList);
                        query.addBindValue(idList);
                        if(!query.execBatch()){
                            qDebug()<<query.lastError().databaseText();
                        }
                    }

                }
            }
        }
    }else{
        qDebug()<<query.lastError().databaseText();
    }


    //记录执行情况

    m1_examSubstepNumberRecord[stepId] = executeResult;



    //只要做过步骤，就给作业安全和会使用列车锤的满分
    // if(m1_executeIndex  ==  1){
    //     sql = QString("UPDATE %2 SET step_object_point = 5 WHERE id = \'%1\'").arg("0E0E00").arg(g_examineExam2TableName);
    //     if(!query.exec(sql)){
    //         qDebug()<<query.lastError().databaseText();
    //     }

    //     sql = QString("UPDATE %2 SET step_object_point = 5 WHERE id = \'%1\'").arg("0E0E01").arg(g_examineExam2TableName);
    //     if(!query.exec(sql)){
    //         qDebug()<<query.lastError().databaseText();
    //     }
    // }


}

//计算运行前检查：考试详细得分（记录到数据库中，详细步骤得分记录在缓存中）
void TcpSocket::dealExamineExamDetailSituation()
{
    qDebug()<<"dealExamineExamDetailSituation()";


    QStringList idList;
    QSqlQuery query(m_detailInformationDB);

    QVariantList stepResultList;
    QVariantList errorReasonList;


    //得到上一个阶段的全部id
    //WHERE execute_step_id is not null

    QString sql = QString("SELECT id FROM %1 WHERE execute_step_id is not null").arg(g_examineExamTableName);
    qDebug()<<"sql:"<<sql;

    if(query.exec(sql)){
        while(query.next()){
            idList.append(query.value(0).toString());
        }
    }else{
        qDebug()<<query.lastError().databaseText();//exam_substep_number
    }

    //计算所有操作步骤的分数
    foreach (QString id, idList) {
        qDebug()<<"步骤的id:"<<id;

        QString errorReason = "";
        int errorReason0 = 0;
        int errorReason2 = 0;
        QString stepResult = "";


        //遍历该步骤下的所有详细步骤
        qDebug()<<"遍历该步骤下的所有详细步骤";
        qDebug()<<"m1_examSubstepNumberHash[id].size(）："<<m1_examSubstepNumberHash[id].size();
        for(QList<QString>::ConstIterator iter =  m1_examSubstepNumberHash[id].constBegin(); iter != m1_examSubstepNumberHash[id].constEnd();iter++){

            if(m1_examSubstepNumberRecord[*iter] == 1){//操作正确
                stepResult = "正确";
            }else if(m1_examSubstepNumberRecord[*iter] == 2){//语音错误
                errorReason2++;
                 stepResult = "错误";
            }else if(m1_examSubstepNumberRecord[*iter] == 0){//操作未操作
                errorReason0++;
                stepResult = "错误";
            }
        }


        if(errorReason0 > 0){
            errorReason += QString("%1个未操作步骤;").arg(errorReason0);
        }
        if(errorReason2 > 0){
            errorReason += QString("%1个错误操作步骤;").arg(errorReason2);
        }
        m1_errorReason[id] = errorReason;
        qDebug()<<"m1_errorReason[id]:"<<m1_errorReason[id];


        errorReasonList.append(m1_errorReason[id]);
        stepResultList.append(stepResult);
    }

    sql = QString("UPDATE %1 SET step_result = ? ,error_reason = ?  WHERE id = ?").arg(g_examineExamTableName);

    query.prepare(sql);
    query.addBindValue(stepResultList);
    query.addBindValue(errorReasonList);
    query.addBindValue(idList);
    qDebug()<<"更新运行前检查的操作步骤:";
    qDebug()<<"idList.size():"<<idList.size();
    qDebug()<<"stepResultList.size():"<<stepResultList.size();
    qDebug()<<"errorReasonList.size():"<<errorReasonList.size();


    if(!query.execBatch()){
        qDebug()<<query.lastError().databaseText();
    }

    emit showPartExamTable(ExamType::ExamineExam);
}

QByteArray TcpSocket::dealSendData(CommondNumber command, const QString &data)
{
    //FF D8 00 10 00 00 00 00 00 00 00 01 00 FF D9 10

    QByteArray hexContent = data.toUtf8();

    qDebug()<<"dealSendData:"<<hexContent;

    int length = hexContent.length() + 15;
    //qDebug()<<"num:"<<length;
    QByteArray lengthByte;
    lengthByte.append((length&(0xff000000))>>24);
    lengthByte.append((length&(0x00ff0000))>>16);
    lengthByte.append((length&(0x0000ff00))>>8);
    lengthByte.append(length&(0x000000ff));

    // short length = hexContent.length() + 15;
    // QByteArray lengthByte;
    // lengthByte.append((length&(0x0000ff00))>>8);
    // lengthByte.append(length&(0x000000ff));

    QByteArray sendMessage;
    sendMessage += MESSAGE_HEADER_L;
    sendMessage += MESSAGE_HEADER_H;//固定头
    sendMessage += lengthByte.at(2);
    sendMessage += lengthByte.at(3);//长度
    // sendMessage += lengthByte.at(0);
    // sendMessage += lengthByte.at(1);//长度

    //命令
    sendMessage +=  command.OneByte;
    sendMessage +=  command.TwoByte;
    sendMessage +=  command.ThreeByte;
    sendMessage +=  command.FourByte;

    //对收到命令的第一个字节 + 80；例如收到10，回复90
    // QString msg = m_command.mid(0,1).toHex();
    // int num = msg.toInt(NULL,16);
    // sendMessage += QByteArray::fromHex(QByteArray::number(num + 128,16)).at(0);
    // sendMessage += m_command.at(1);
    // sendMessage +=  m_command.at(2);
    // sendMessage +=  m_command.at(3);

    SerialNumber serialNumber;//序列号
    serialNumber.OneByte = 0x00;
    serialNumber.TwoByte = 0x00;
    serialNumber.ThreeByte = 0x00;
    serialNumber.FourByte = 0x01;
    sendMessage.append((char*)&serialNumber, sizeof(serialNumber));//结构体转QByteArry

    sendMessage += hexContent;//内容

    sendMessage += MESSAGE_TAIL_L;
    sendMessage += MESSAGE_TAIL_H;

    //计算异或校验
    uchar checkResult = 0x00;
    for (int i = 0; i < length - 1; i++) {
        checkResult ^= sendMessage.at(i);
    }
    sendMessage += checkResult;

    //qDebug()<<"sendMessage:"<<sendMessage;

    return sendMessage;
}
//自动计算回复，命令类型加80
QByteArray TcpSocket::dealSendData2(const QString &data)
{
    //FF D8 00 10 00 00 00 00 00 00 00 01 00 FF D9 10

    QByteArray hexContent = data.toUtf8();

    int length = hexContent.length() + 15;
    // qDebug()<<"num:"<<length;
    QByteArray lengthByte;
    lengthByte.append((length&(0xff000000))>>24);
    lengthByte.append((length&(0x00ff0000))>>16);
    lengthByte.append((length&(0x0000ff00))>>8);
    lengthByte.append(length&(0x000000ff));

    QByteArray sendMessage;
    sendMessage += MESSAGE_HEADER_L;
    sendMessage += MESSAGE_HEADER_H;//固定头
    sendMessage += lengthByte.at(2);
    sendMessage += lengthByte.at(3);//长度

    //对收到命令的第一个字节 + 80；例如收到10，回复90
    QString msg = m_command.mid(0,1).toHex();
    int num = msg.toInt(NULL,16);
    sendMessage += QByteArray::fromHex(QByteArray::number(num + 128,16)).at(0);
    sendMessage += m_command.at(1);
    sendMessage +=  m_command.at(2);
    sendMessage +=  m_command.at(3);

    SerialNumber serialNumber;//序列号
    serialNumber.OneByte = 0x00;
    serialNumber.TwoByte = 0x00;
    serialNumber.ThreeByte = 0x00;
    serialNumber.FourByte = 0x01;
    sendMessage.append((char*)&serialNumber, sizeof(serialNumber));//结构体转QByteArry

    sendMessage += hexContent;//内容

    sendMessage += MESSAGE_TAIL_L;
    sendMessage += MESSAGE_TAIL_H;

    //计算异或校验
    uchar checkResult = 0x00;
    for (int i = 0; i < length - 1; i++) {
        checkResult ^= sendMessage.at(i);
    }
    sendMessage += checkResult;

    //  qDebug()<<"sendMessage:"<<sendMessage;

    return sendMessage;
}

QByteArray TcpSocket::dealSendData3(CommondNumber command, const QByteArray data)
{
    // qDebug() << "dealSendData3 处理数据的线程：" <<QThread::currentThreadId() << QThread::currentThread();

    int length = data.length() + 15;
    qDebug()<<"data.length():"<<length;
    QByteArray lengthByte;
    lengthByte.append((length&(0xff000000))>>24);
    lengthByte.append((length&(0x00ff0000))>>16);
    lengthByte.append((length&(0x0000ff00))>>8);
    lengthByte.append(length&(0x000000ff));

    //使用short类型
    // short length = hexContent.length() + 15;
    // QByteArray lengthByte;
    // lengthByte.append((length&(0x0000ff00))>>8);
    // lengthByte.append(length&(0x000000ff));

    QByteArray sendMessage;
    sendMessage += MESSAGE_HEADER_L;
    sendMessage += MESSAGE_HEADER_H;//固定头
    sendMessage += lengthByte.at(2);
    sendMessage += lengthByte.at(3);//长度
    // sendMessage += lengthByte.at(0);
    // sendMessage += lengthByte.at(1);//长度

    //命令
    sendMessage +=  command.OneByte;
    sendMessage +=  command.TwoByte;
    sendMessage +=  command.ThreeByte;
    sendMessage +=  command.FourByte;

    //对收到命令的第一个字节 + 80；例如收到10，回复90
    // QString msg = m_command.mid(0,1).toHex();
    // int num = msg.toInt(NULL,16);
    // sendMessage += QByteArray::fromHex(QByteArray::number(num + 128,16)).at(0);
    // sendMessage += m_command.at(1);
    // sendMessage +=  m_command.at(2);
    // sendMessage +=  m_command.at(3);

    SerialNumber serialNumber;//序列号
    serialNumber.OneByte = 0x00;
    serialNumber.TwoByte = 0x00;
    serialNumber.ThreeByte = 0x00;
    serialNumber.FourByte = 0x01;
    sendMessage.append((char*)&serialNumber, sizeof(serialNumber));//结构体转QByteArry

    sendMessage += data;//内容

    sendMessage += MESSAGE_TAIL_L;
    sendMessage += MESSAGE_TAIL_H;

    //计算异或校验
    uchar checkResult = 0x00;
    for (int i = 0; i < length - 1; i++) {
        checkResult ^= sendMessage.at(i);
    }
    sendMessage += checkResult;

    //  qDebug()<<"sendMessage:"<<sendMessage;

    return sendMessage;
}


QString TcpSocket::getIP() const
{
    return this->m_ip;
}

int TcpSocket::getPort() const
{
    return this->m_port;
}

qintptr TcpSocket::getSocketDescriptor()
{
    return this->m_socketDescriptor;
}

void TcpSocket::disconnected()
{
    qDebug()<<"TcpSocket::disconnected()";

    emit clientDisconnected(m_socketDescriptor);

    if(m_ip == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].first && m_port == g_Client2Hash[ClientHashEnum::ExamineExamUnityEquipment].second){
        emit conveyEquipmentStatusType(EquipmentStatusType::ExamineExamUnityEquipmentOffline);
    }else if(m_ip == g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].first && m_port == g_Client2Hash[ClientHashEnum::RouteExamUnityEquipment].second){
        emit conveyEquipmentStatusType(EquipmentStatusType::RouteExamUnityEquipmentOffline);
    }else if(m_ip == g_Client2Hash[ClientHashEnum::LowerComputerCommucationEquipment].first && m_port == g_Client2Hash[ClientHashEnum::LowerComputerCommucationEquipment].second){
        emit conveyEquipmentStatusType(EquipmentStatusType::LowerComputerEquipmentOffline);
    }else if(m_ip == g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].first && m_port == g_Client2Hash[ClientHashEnum::TampingHomeworkEquipment].second){
        emit conveyEquipmentStatusType(EquipmentStatusType::TampingHomeworkEquipmentOffline);
    }
}

void TcpSocket::abort()
{
    m_socket->abort();
}

QString TcpSocket::getOrCode(const QByteArray &data)
{
    int len = data.length();

    uchar tempResult = 0x00;

    for (int i = 0; i < len; i++) {
        tempResult ^= data.at(i);
    }

    QByteArray res;
    res.resize(1);
    res[0] = tempResult;
    QString result =  res.toHex().toUpper();

    //qDebug()<<"得到异或校验结果";

    return result;
}

QString TcpSocket::byteArrayToHexStr(const QByteArray &data)
{
    QString tmp = "";
    QString hex = data.toHex();

    for(int i = 0; i < hex.length();i += 2){
        tmp += hex.mid(i ,2) + " ";
    }

    return tmp.trimmed().toUpper();
}

